package com.example.que2;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

public class ThreadSafeQueue<E> {
    private AtomicReference<Node<E>> head = new AtomicReference<>(null);
    private AtomicReference<Node<E>> tail = new AtomicReference<>(null);
    private AtomicInteger size = new AtomicInteger(0);

    public ThreadSafeQueue() {
        Node<E> node = new Node<>(null, null);
        head.set(node);
        tail.set(node);
    }

    public void addLast(E e) {
        if (null == e) {
            throw new IllegalArgumentException("e is null");
        }
        Node<E> node = new Node<>(e, null);
        Node<E> preNode = tail.getAndSet(node);
        preNode.setNext(node);
        size.getAndIncrement();
    }

    public E removeFirst() {
        Node<E> headNode, valueNode;
        do {
            headNode = head.get();
            valueNode = headNode.getNext();
        } while (valueNode != null && !head.compareAndSet(headNode, valueNode));
        E value = (valueNode == null) ? null : valueNode.getElement();
        size.getAndDecrement();
        return value;
    }

    static class Node<E> {
        volatile E element;
        Node<E> next;

        public Node(E element, Node<E> next) {
            this.element = element;
            this.next = next;
        }

        public E getElement() {
            return element;
        }

        public void setElement(E element) {
            this.element = element;
        }

        public Node<E> getNext() {
            return next;
        }

        public void setNext(Node<E> next) {
            this.next = next;
        }
    }
}
